home *** CD-ROM | disk | FTP | other *** search
Text File | 2004-09-01 | 34.6 KB | 1,064 lines |
- % Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved.
- %
- % This software is provided AS-IS with no warranty, either express or
- % implied.
- %
- % This software is distributed under license and may not be copied,
- % modified or distributed except as expressly authorized under the terms
- % of the license contained in the file LICENSE in this distribution.
- %
- % For more information about licensing, please refer to
- % http://www.ghostscript.com/licensing/. For information on
- % commercial licensing, go to http://www.artifex.com/licensing/ or
- % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
- % San Rafael, CA 94903, U.S.A., +1(415)492-9861.
-
- % $Id: pdf_main.ps,v 1.71.2.5 2004/08/31 18:18:51 ray Exp $
- % pdf_main.ps
- % PDF file- and page-level operations.
-
- /.setlanguagelevel where { pop 2 .setlanguagelevel } if
- .currentglobal true .setglobal
- /pdfdict where { pop } { /pdfdict 100 dict def } ifelse
- pdfdict begin
-
- % Patch in an obsolete variable used by some third-party software.
- /#? false def
-
- % Test whether the current output device handles pdfmark.
- /.writepdfmarkdict 1 dict dup /pdfmark null put readonly def
- /.writepdfmarks { % - .writepdfmarks <bool>
- currentdevice //.writepdfmarkdict .getdeviceparams
- mark eq { false } { pop pop true } ifelse
- systemdict /DOPDFMARKS known or
- } bind def
-
- % For simplicity, we use a single interpretation dictionary for all
- % PDF graphics execution, even though this is too liberal.
- /pdfopdict mark
- objopdict { } forall
- drawopdict { } forall
- /endstream { exit } bind
- (%%EOF) cvn { exit } bind % for filters
- % PDF 1.1 operators
- /BX { /BXlevel BXlevel 1 add store } bind
- /EX { /BXlevel BXlevel 1 sub store } bind
- /PS { cvx exec } bind
- % PDF 1.2 operators
- /BMC { pop } bind
- /BDC { pop pop } bind
- /EMC { }
- /MP { pop } bind
- /DP { pop pop } bind
- .dicttomark readonly def
-
- % ======================== Main program ======================== %
-
- end % pdfdict
- userdict begin
-
- /defaultfontname /Times-Roman def
-
- % Make sure the registered encodings are loaded, so we don't run the risk
- % that some of the indices for their names will overflow the packed
- % representation. (Yes, this is a hack.)
- SymbolEncoding pop
- DingbatsEncoding pop
-
- % Redefine 'run' so it recognizes PDF files.
- systemdict begin
- /.runps /run load def
- /run {
- dup type /filetype ne { (r) file } if
- dup ( ) .peekstring {
- (%) eq {
- dup ( ) .peekstring {
- (%PDF-) eq {
- dup (%stdin) (r) file eq {
- % Copy PDF from stdin to temporary file then run it.
- null (w+) //systemdict /.tempfile get exec exch 3 1 roll
- % stack: tempname stdin tempfile
- 64000 string
- {
- % stack: tempname stdin tempfile string
- 2 index 1 index readstring
- exch 3 index exch writestring
- not { exit } if
- }
- loop
- pop exch closefile
- % stack: tempname tempfile
- dup 0 setfileposition
- dup runpdf
- closefile deletefile
- } {
- runpdf
- } ifelse
- } {
- cvx .runps % doesn't start with %PDF-
- } ifelse
- } {
- pop cvx .runps % didn't read 5 characters
- } ifelse
- } {
- cvx .runps % didn't start with %
- } ifelse
- } {
- pop closefile % file was empty
- } ifelse
- } bind odef
- currentdict /runpdfstring .undef
-
-
- /runpdfbegin { % <file> runpdf -
- userdict begin
- % It turns out that the PDF interpreter uses memory more
- % effectively if it is run under at least one level of save.
- % This is counter-intuitive, and we don't understand why it happens,
- % but the improvement is significant.
- /PDFTopSave save def
- 0 setobjectformat
- /Page# null def
- /Page null def
- /DSCPageCount 0 def
- /PDFSave null def
- GS_PDF_ProcSet begin
- pdfdict begin
- pdfopen begin
- Trailer /Root oget /Pages oget /CropBox knownoget
- { oforce_array mark /CropBox 3 -1 roll /PAGES pdfmark
- }
- if
- /FirstPage where
- { pop FirstPage dup pdfpagecount gt
- { (\nRequested FirstPage is greater than the number of pages in the file: ) print
- pdfpagecount = flush
- } if
- } {
- 1
- } ifelse
- /LastPage where { pop LastPage pdfpagecount .min } { pdfpagecount } ifelse
- 1 index 1 index gt
- { ( No pages will be processed \(FirstPage > LastPage\).) = flush }
- { QUIET not
- { (Processing pages ) print 1 index =only ( through ) print dup =only
- (.) = flush
- }
- if
- }
- ifelse
- } bind def
-
- /dopdfpages { % firstpage# lastpage# dopdfpages -
- << /PDFScanRules true >> setuserparams % set scanning rules for PDF vs. PS
- 1 exch
- { dup /Page# exch store
- QUIET not { (Page ) print dup == flush } if
- pdfgetpage pdfshowpage
- } for
- << /PDFScanRules null >> setuserparams % restore scanning rules for PS
- } bind def
-
- /runpdfend {
- Repaired { printrepaired } if
- currentdict pdfclose
- end % temporary dict
- end % pdfdict
- end % GS_PDF_ProcSet
- PDFTopSave restore
- end % userdict
- } bind def
-
- /runpdf { % <file> runpdf -
- runpdfbegin
- dopdfpages
- runpdfend
- } bind def
-
- end % systemdict
- % Redefine the procedure that the C code uses for running piped input.
- % It is OK to use { (%stdin) run } here, because a startjob cannot occur.
- /.runstdin {
- { (%stdin) run } execute0
- } bind def
-
- end % userdict
- pdfdict begin
-
- % ======================== File parsing ======================== %
-
- % Read the cross-reference and trailer sections.
-
- /traileropdict mark
- (<<) cvn { mark } bind
- (>>) cvn { { .dicttomark } stopped {
- ( **** File has unbalanced >> in trailer.\n) pdfformaterror
- } if } bind
- ([) cvn { mark } bind % ditto
- (]) cvn dup load
- % /true true % see .pdfexectoken in pdf_base.ps
- % /false false % ibid.
- % /null null % ibid.
- /R { /resolveR cvx 3 packedarray cvx } bind % see Objects below
- /startxref /exit load
- .dicttomark readonly def
-
- % Because of EOL conversion, lines with fixed contents might be followed
- % by one or more blanks.
- /lineeq % <filestr> <conststr> lineeq <bool>
- { anchorsearch
- { pop { ( ) anchorsearch not { () eq exit } if pop } loop }
- { pop false }
- ifelse
- } bind def
- /linene { lineeq not } bind def
-
- % Read the cross-reference table.
- /readxref % <pos> readxref <trailerdict>
- {
- PDFoffset add PDFfile exch setfileposition
- % In some PDF files, this position actually points to
- % white space before the xref line. Skip over this here.
- { PDFfile fileposition PDFfile read pop 32 gt { exit } if pop
- } loop
- PDFfile exch setfileposition
- 0 % Initialize xref table error counter
-
- % The PDF specification says that the 'xref' must be on a line
- % by itself. The code here formerly used readline and linene to
- % check this. However, Acrobat Reader only requires the line to
- % begin with 'xref', and there are enough applications producing
- % non-compliant PDF files that we have to do this too.
- PDFfile pdfstring 0 4 getinterval readstring pop
- (xref) ne { /readxref cvx /syntaxerror signalerror } if
- % Store the xref table entry position for each object.
- { PDFfile token pop % first object # or trailer
- dup /trailer eq { pop exit } if
- PDFfile pdfstring readline pop
- token pop % entry count
- exch pop % remove last
- % This section might be adding new objects:
- % ensure that Objects and Generations are big enough.
- % stack: <err count> <first obj> <entry count>
- 2 copy add growPDFobjects
- PDFfile fileposition
- 3 1 roll % stack: <err count> <filepos> <first obj> <entry count>
- { % stack: <err count> <file pos> <obj num>
- % Read xref line
- PDFfile pdfstring readline pop
- token pop % object position
- exch token pop % generation #
- exch token pop % n or f
- exch pop % Stack: <err count> <file pos> <obj#> <loc> <gen#> <tag>
- dup /n eq { % xref line tag is /n
- pop % pop dup of line tag
- Objects 3 index lget null eq { % later update might have set it
- setxrefentry
- } if
- }
- { % xref line tag was not /n
- /f ne % verify that the tag was /f
- { /setxrefentry cvx /syntaxerror signalerror
- } if
- } ifelse
- pop pop % pop <obj location> and <gen num>
- % Check if line length is 20 chars (Adobe spec.)
- exch % stack: <err count> <obj num> <file pos>
- PDFfile fileposition % <err count> <obj#> <old pos> <new pos>
- dup 4 1 roll % <err count> <new Pos> <obj#> <old pos> <new pos>
- exch sub 20 ne % <err count> <new Pos> <obj#> <bool>
- { 3 -1 roll 1 add 3 1 roll % Increment error count
- } if
- 1 add % increment object number
- } repeat
- pop pop % pop <file pos> <obj #>
- } loop
- 0 ne {
- ( **** Warning: length of some xref entries is not equal to 20 bytes.\n)
- pdfformaterror
- } if
- PDFfile traileropdict .pdfrun
- } bind def
-
- % Open a PDF file and read the header, trailer, and cross-reference.
- /pdfopen { % <file> pdfopen <dict>
- % Color space substitution in PDF is handled somewhat differently
- % than in PostScript. A given device color space will be substituted
- % if the corresponding "Default..." entry exists in the Page's
- % Resource dictionary (which might be inhereted); there is no
- % UseCIEColor to enable/disable color mapping.
- %
- % This behavior is achieved by always setting UseCIEColor to true
- % in the page device dictionary. If the value of this parameter was
- % originally false (i.e.: the output device does not perform color
- % space substitution by default), the instances DefaultGray,
- % DefaultRGB, and DefaultCMYK of the (local) ColorSpace category
- % are redefined to be DeviceGray, DeviceRGB, and DeviceCMYK,
- % respectively. This is not done if UseCIEColor is true by default,
- % as in that case color substitution is presumably desired even
- % if the file does not request it.
- currentpagedevice /UseCIEColor .knownget dup { pop } if not
- { .currentglobal false .setglobal
- /DefaultGray { /DeviceGray } cvlit /ColorSpace defineresource pop
- /DefaultRGB { /DeviceRGB } cvlit /ColorSpace defineresource pop
- /DefaultCMYK { /DeviceCMYK } cvlit /ColorSpace defineresource pop
- .setglobal
- }
- if
- pdfopenfile begin
- pdfopencache
- .writepdfmarks {
- % Copy bookmarks (outline) to the output.
- Trailer /Root oget /Outlines knownoget {
- /First knownoget {
- { dup writeoutline /Next knownoget not { exit } if } loop
- } if
- } if
- } if % end .writepdfmarks
- currentdict end
- } bind def
-
- /pdfopencache { % - pdfopencache -
- % Create and initialize some caches.
- /PageCount pdfpagecount def
- /PageNumbers PageCount 65534 .min dict def
- /PageIndex PageCount 65534 .min array def
- } bind def
-
- /pdfopenfile { % <file> pdfopenfile <dict>
- pdfdict readonly pop % can't do it any earlier than this
- 15 dict begin
- /LocalResources 0 dict def
- /DefaultQstate //null def % establish binding
- /Printed where { pop } {
- % Guess whether the output device is a printer.
- /Printed currentpagedevice /OutputFile known def
- } ifelse
- /PSLevel1 where { pop } { /PSLevel1 false def } ifelse
- % NB: PDFfile is used outside of the PDF code to determine that a
- % PDF job is being processed; to not change or hide this key.
- cvlit /PDFfile exch def
- /PDFsource PDFfile def
- /Repaired false def
- PDFfile dup 0 setfileposition pdfstring readstring
- not {/pdfopen cvx /syntaxerror signalerror} if
- (%PDF-) search not {/pdfopen cvx /syntaxerror signalerror} if
- length /PDFoffset exch def pop cvr /PDFversion exch def
- % Read the last cross-reference table.
- count /pdfemptycount exch def
- /Trailer << >> def % Initialize to an emptry dict.
- { initPDFobjects findxref readxref } .internalstopped {
- % Read failed. Attempt to recover xref data.
- print_xref_warning
- count pdfemptycount sub { pop } repeat % remove anything left by readxref
- search_objects
- search_trailer
- } { /Trailer exch def
- % Read any previous cross-reference tables.
- Trailer
- { /Prev knownoget not { exit } if
- { readxref } .internalstopped {
- % Read failed. Attempt to recover xref data.
- print_xref_warning
- count pdfemptycount sub { pop } repeat % remove anything left by readxref
- search_objects
- search_trailer
- exit
- } if
- % The PDF spec. says that each trailer dict should contain the required
- % entries. However we have seen a PDF file that only has a Prev entry in
- % the initial trailer dict. Acrobat complains but it accepts these files.
- % To work with these files, we are copying any entries which we find in
- % a previous trailer dict which are not present in the initial dict.
- dup {
- Trailer 2 index known {
- pop pop % discard if key already present
- } {
- Trailer 3 1 roll put % add key if not present
- } ifelse
- } forall
- } loop
- } ifelse
- Trailer /Encrypt knownoget {
- pop
- pdf_process_Encrypt % signal error
- } if
- currentdict end
- } bind def
-
- % Skip backward over the %%EOF at the end of the PDF file, and read
- % the preceding startxref line. The PDF specification unambiguously
- % requires that the %%EOF appear on a line by itself, and that the
- % startxref and the following position value appear on separate lines;
- % however, some applications (including, apparently, Acrobat Distiller
- % on the Macintosh) may add up to 2K of garbage after the %%EOF, and some
- % other applications also truncate the %%EOF to %%EO, and/or put the
- % startxref and the following value on the same line.
- % A file reported from Distiller 3.02b for AIX 4.1.1 has 2076 bytes
- % of garbage. The tolerance is increased to 4K to cover future
- % applications and bigger allocation units.
- /findxref { % - findxref <xrefpos>
- PDFfile dup dup 0 setfileposition bytesavailable
- dup /PDFfilelen exch def
- % Find the last %%EOF string (within 4096 bytes)
- 4096 sub PDFoffset .max
- 2 copy setfileposition
- PDFfilelen exch sub string 1 index exch readstring pop {
- (\015%%EO) search { % Adobe can handle truncated key string
- pop pop % if found, keep searching 'post' string
- } {
- (\012%%EO) search
- { pop pop } { exit } ifelse % exit if neither string found
- } ifelse
- } loop
- PDFfilelen exch length sub 4 sub PDFoffset .max exch 1 index setfileposition
- % Stack: eofpos
- % Check for whether this is, in fact, a valid PDF file.
- dup PDFfilelen exch sub dup dup 7 gt exch 5 lt or {
- pop true
- } {
- string PDFfile exch readstring pop
- dup (%%EOF\n) eq exch dup (%%EOF\r) eq
- exch dup (%%EOF\r\n) eq exch (%%EOF) eq or or or not
- } ifelse {
- ( **** Warning: File has a corrupted %%EOF marker, or garbage after %%EOF.\n)
- pdfformaterror
- } if
- PDFfile exch setfileposition
- % Now read the startxref and xref start position.
- prevline token not { null } if dup type /integertype eq {
- exch pop cvi % xref start position
- exch PDFfile exch setfileposition
- prevline dup (startxref) linene {
- % startxref not on a line by itself. We have found PDF from
- % www.verypdf.com in which the startxref was on the same line as
- % the end of trailer dictionary. Check for this. Note: This
- % violates the spec.
- dup (startxref) search {
- % found startxref - print warning
- pop pop pop % clear strings from search
- ( **** Warning: format of the startxref line in this file is invalid.\n)
- pdfformaterror
- } { % no startxref - we have a problem.
- /findxref cvx /syntaxerror signalerror
- } ifelse
- } if
- pop pop
- } { % else, this file has 'startxref #####' format
- (startxref) ne { /findxref cvx /syntaxerror signalerror } if
- cvi % xref start position
- ( **** Warning: format of the startxref line in this file is invalid.\n)
- pdfformaterror
- exch PDFfile exch setfileposition
- } ifelse
- } bind def
- /stderrfile (%stderr) (w) file def
- /stderrprint { % <string> stderrprint -
- //stderrfile dup 3 -1 roll writestring flushfile
- } bind def
- /pdfformaterror { % <string> pdfformaterror -
- stderrprint
- /Repaired true store
- } bind def
-
- /knownoget_safe
- { knownoget
- } odef
-
- /printProducer {
- Trailer /Info { knownoget_safe } stopped { false } if {
- /Producer knownoget not { null } if
- } {
- null
- } ifelse
- dup null eq {
- pop
- } {
- ( **** The file was produced by: \n **** >>>> ) stderrprint
- % Handle a Unicode Producer.
- (\376\377) anchorsearch {
- pop dup length 2 idiv string 0 1 2 index length 1 sub {
- % Stack: origstr newstr i
- 1 index exch 3 index 1 index 2 mul 1 add get put
- } for exch pop
- } if
- stderrprint
- ( <<<<\n) stderrprint
- } ifelse
- } bind def
- /printrepaired {
- (\n **** This file had errors that were repaired or ignored.\n)
- stderrprint
- printProducer
- ( **** Please notify the author of the software that produced this\n)
- stderrprint
- ( **** file that it does not conform to Adobe's published PDF\n)
- stderrprint
- ( **** specification.\n\n)
- stderrprint
- } bind def
-
- % Write the outline structure for a file. Uses linkdest (below).
- /writeoutline % <outlinedict> writeoutline -
- { mark
- 0 2 index /First knownoget
- { { exch 1 add exch /Next knownoget not { exit } if } loop }
- if
- % stack: dict mark count
- dup 0 eq
- { pop 1 index
- }
- { 2 index /Count knownoget { 0 lt { neg } if } if
- /Count exch 3 index
- }
- ifelse linkdest /Title oget /Title exch /OUT pdfmark
- /First knownoget
- { { dup writeoutline /Next knownoget not { exit } if } loop }
- if
- } bind def
-
- % Close a PDF file.
- /pdfclose % <dict> pdfclose -
- { begin
- PDFfile closefile
- end
- } bind def
-
- % ======================== Page accessing ======================== %
-
- % Get a (possibly inherited) attribute of a page.
- /pget % <pagedict> <key> pget <value> -true-
- % <pagedict> <key> pget -false-
- { 2 copy knownoget
- { exch pop exch pop true
- }
- { exch /Parent knownoget
- { exch pget }
- { pop false }
- ifelse
- }
- ifelse
- } bind def
-
- % Get the value of a resource on a given page.
- /rget { % <resname> <pagedict> <restype> rget <value> -true-
- % <resname> <pagedict> <restype> rget -false-
- LocalResources 1 index knownoget {
- 3 index knownoget
- } {
- false
- } ifelse {
- exch pop exch pop exch pop true
- } {
- exch /Resources pget {
- exch knownoget { exch knownoget } { pop false } ifelse
- } {
- pop pop false
- } ifelse
- } ifelse
- } bind def
-
- % Get the total number of pages in the document.
- /pdfpagecount % - pdfpagecount <int>
- { Trailer /Root oget /Pages oget /Count oget
- } bind def
-
- % Find the N'th page of the document by iterating through the Pages tree.
- % The first page is numbered 1.
- /pdffindpageref { % <int> pdffindpage <objref>
- dup Trailer /Root oget /Pages get
- { % We should be able to tell when we reach a leaf
- % by finding a Type unequal to /Pages. Unfortunately,
- % some files distributed by Adobe lack the Type key
- % in some of the Pages nodes! Instead, we check for Kids.
- dup oforce /Kids knownoget not { exit } if
- exch pop null
- 0 1 3 index length 1 sub {
- 2 index exch get
- dup oforce dup /Kids known { /Count oget } { pop 1 } ifelse
- % Stack: index kids null noderef count
- dup 5 index ge { pop exch pop exit } if
- 5 -1 roll exch sub 4 1 roll pop
- } for exch pop
- % Stack: index null|noderef
- dup null eq { pop pop 1 null exit } if
- } loop
- % Stack: index countleft noderef
- 1 index 1 ne { pop pop /pdffindpage cvx /rangecheck signalerror } if
- exch pop
- PageIndex 2 index 1 sub 65533 .min 2 index oforce put
- PageNumbers 1 index oforce 3 index dup 65534 le
- { put }
- { pop pop pop } % don't store more than 65534 pagenumbers
- ifelse
- exch pop
- } bind def
- /pdffindpage { % <int> pdffindpage <pagedict>
- pdffindpageref oforce
- } bind def
-
- % Find the N'th page of the document.
- % The first page is numbered 1.
- /pdfgetpage % <int> pdfgetpage <pagedict>
- { PageIndex 1 index 1 sub dup 65533 lt
- { get }
- { pop pop null }
- ifelse
- dup null ne
- { exch pop oforce }
- { pop pdffindpage }
- ifelse
- } bind def
-
- % Find the page number of a page object (inverse of pdfgetpage).
- /pdfpagenumber % <pagedict> pdfpagenumber <int>
- { % We use the simplest and stupidest of all possible algorithms....
- PageNumbers 1 index .knownget
- { exch pop
- }
- { 1 1 PageCount 1 add % will give a rangecheck if not found
- { dup pdfgetpage oforce 2 index eq { exit } if pop
- }
- for exch pop
- }
- ifelse
- } bind def
-
- % Display a given page.
- /boxrect % <llx> <lly> <urx> <ury> boxrect <x> <y> <w> <h>
- { exch 3 index sub exch 2 index sub
- } bind def
- /resolvedest { % <name|string|other> resolvedest <other|null>
- dup type /nametype eq {
- Trailer /Root oget /Dests knownoget {
- exch knownoget not { null } if
- } {
- pop null
- } ifelse
- } {
- dup type /stringtype eq {
- Trailer /Root oget /Names knownoget {
- /Dests knownoget {
- exch nameoget
- } {
- pop null
- } ifelse
- } {
- pop null
- } ifelse
- } if
- } ifelse
- } bind def
- /linkdest { % <link|outline> linkdest
- % ([/Page <n>] /View <view> | ) <link|outline>
- dup /Dest knownoget
- { resolvedest
- dup type /dicttype eq { /D knownoget not { null } if } if
- dup null eq
- { pop }
- { dup 0 oget
- dup type /dicttype eq {
- dup /Type knownoget {
- /Page eq {
- pdfpagenumber
- } if
- } if
- } if
- dup type /integertype ne
- { pop }
- { /Page exch 4 -2 roll }
- ifelse
- dup length 1 sub 1 exch getinterval /View exch 3 -1 roll
- }
- ifelse
- }
- if
- } bind def
- % <pagedict> mark ... -proc- -
- /namedactions 8 dict dup begin
- /FirstPage {
- /Page 1 3 -1 roll
- } def
- /LastPage {
- counttomark 2 add index pdfpagecount /Page exch 3 -1 roll
- } def
- /NextPage {
- counttomark 2 add index pdfpagenumber 1 add /Page exch 3 -1 roll
- } def
- /PrevPage {
- counttomark 2 add index pdfpagenumber 1 sub /Page exch 3 -1 roll
- } def
- end readonly def
- % <pagedict> <annotdict> -proc- -
- /annottypes 5 dict dup begin
- /Text {
- mark exch
- { /Rect /Open /Contents }
- { 2 copy knownoget { 3 -1 roll } { pop } ifelse }
- forall pop /ANN pdfmark
- } bind def
- /Link {
- mark exch
- dup /C knownoget { /Color exch 3 -1 roll } if
- { /Rect /Border }
- { 2 copy knownoget { 3 -1 roll } { pop } ifelse }
- forall dup /A knownoget {
- dup /URI known {
- /A mark 3 2 roll % <<>> /A [ <<action>>
- { oforce } forall
- .dicttomark
- 3 2 roll
- } {
- dup /D knownoget {
- exch pop exch dup length dict copy dup /Dest 4 -1 roll put
- } {
- /N knownoget { % Assume /S /Named
- namedactions exch .knownget { exec } if
- } if
- } ifelse
- } ifelse
- } if
- linkdest pop /LNK pdfmark
- } bind def
- end readonly def
-
- % **** The following procedure should not be changed to allow clients
- % **** to directly interface with the constituent procedures. GSview
- % **** and some Artifex customers rely on the pdfshowpage_init,
- % **** pdfshowpage_setpage, pdfshowpage_finish so all logic should be
- % **** implemented in one of those three procedures.
- /pdfshowpage % <pagedict> pdfshowpage -
- { dup /Page exch store
- pdfshowpage_init
- pdfshowpage_setpage
- pdfshowpage_finish
- } bind def
-
- /pdfpagecontents % <pagedict> pdfpagecontents <contents>
- { } bind def
-
- /pdfshowpage_init % <pagedict> pdfshowpage_init <pagedict>
- { /DSCPageCount DSCPageCount 1 add store
- } bind def
-
- /.pdfshowpage_Install { % <pagedict> [<prevproc>] .pdfshowpage_Install -
- exch
- % We would like to clip to the CropBox here, but the subsequent
- % initgraphics would override it. Instead, we have to handle it
- % in graphicsbeginpage.
- dup /CropBox pget dup {exch pop} if systemdict /UseCropBox known and {
- dup /CropBox pget pop
- } {
- dup /MediaBox pget pop % There has to be a MediaBox
- } ifelse
- % stack: [<prevproc>] <pagedict> <Crop|Media Box>
- exch pop oforce_array % done with the pagedict
- systemdict /PDFFitPage known {
- PDFDEBUG { (Fiting PDF to imageable area of the page.) = flush } if
- currentpagedevice /.HWMargins get aload pop
- currentpagedevice /PageSize get aload pop
- 3 -1 roll sub 3 1 roll exch sub exch
- % stack: [<prevproc>] <pagedict> <Crop|Media Box> Xmin Ymin Xmax Ymax
- PDFDEBUG { ( Translate up by [ ) print 3 index =print (, ) print 2 index =print ( ]) = flush } if
- 3 index 3 index translate % move origin up to imageable area
- 2 index sub exch 3 index sub exch 4 2 roll pop pop
- % stack: [Box] XImageable YImageable
- 2 index aload pop 2 index sub exch 3 index sub exch 4 2 roll pop pop
- % stack: [Box] XImageable YImageable XBox YBox
- 3 -1 roll exch div 3 1 roll div .min
- PDFDEBUG { ( Scale by ) print dup = flush } if
- dup scale
- } if
- % Now translate to the origin given in the Crop|Media Box
- dup 0 get neg exch 1 get neg translate
- 0 get
- exec
- } bind def
-
- /pdfshowpage_setpage { % <pagedict> pdfshowpage_setpage <pagedict>
- 5 dict begin % for setpagedevice
- % Stack: pagedict
- % UseCIEColor is always true for PDF; see the comment in runpdf above
- /UseCIEColor true def
- currentpagedevice /Orientation 2 index /Rotate pget not { 0 } if 90 idiv
- % Rotate specifies *clockwise* rotation!
- neg 3 and def
- % Stack: pagedict currentpagedict
- 1 index /CropBox pget dup {exch pop} if systemdict /UseCropBox known and {
- % Set the page size.
- 1 index /CropBox pget pop oforce_elems
- boxrect 2 array astore /PageSize exch def pop pop
- } {
- 1 index /MediaBox pget {
- % Set the page size.
- oforce_elems boxrect 2 array astore /PageSize exch def pop pop
- } if
- } ifelse
- % Don't change the page size if we are going to fit the PDF to the page
- systemdict /PDFFitPage known { currentdict /PageSize undef } if
- dup /Install .knownget {
- % Don't let the Install procedure get more deeply
- % nested after every page.
- dup type dup /arraytype eq exch /packedarraytype eq or {
- dup length 4 eq {
- dup 2 get /.pdfshowpage_Install load eq {
- 1 get 0 get % previous procedure
- } if
- } if
- } if
- } {
- { }
- } ifelse 1 array astore
- 2 index exch /.pdfshowpage_Install load /exec load
- 4 packedarray cvx
- % Stack: pagedict currentpagedict installproc
- /Install exch def
- % Stack: pagedict currentpagedict
- pop currentdict end setpagedevice
- } bind def
-
- /pdfshowpage_finish { % <pagedict> pdfshowpage_finish -
- save /PDFSave exch store
- /PDFdictstackcount countdictstack store
- (before exec) VMDEBUG
-
- % set up color space substitution (this must be inside the page save)
- pdfshowpage_setcspacesub
-
- .writepdfmarks {
-
- % Copy the crop box.
- dup /CropBox knownoget {
- oforce_array
-
- % .pdfshowpage_Install translates the origin -
- % do same here with the CropBox.
-
- 1 index /CropBox pget dup {exch pop} if systemdict /UseCropBox known and {
- 1 index /CropBox pget pop
- } {
- 1 index /MediaBox pget pop % There has to be a MediaBox
- } ifelse
- oforce_array
- dup 0 get exch 1 get % [] tx ty
- 2 index 0 get 2 index sub 3 index exch 0 exch put
- 2 index 2 get 2 index sub 3 index exch 2 exch put
- 2 index 1 get 1 index sub 3 index exch 1 exch put
- 2 index 3 get 1 index sub 3 index exch 3 exch put
- pop pop
-
- % If the page has been rotated, rotate the CropBox.
- mark /CropBox 3 -1 roll
- 3 index /Rotate pget {
- 90 idiv 1 and 0 ne {
- aload pop 4 -2 roll exch 4 2 roll exch 4 array astore
- } if
- } if
- /PAGE pdfmark
- } if
-
- % Copy annotations and links.
- dup /Annots knownoget {
- 0 1 2 index length 1 sub
- { 1 index exch oget
- dup /Subtype oget annottypes exch .knownget { exec } { pop } ifelse
- }
- for pop
- } if
-
- } if % end .writepdfmarks
-
- % Display the actual page contents.
- 6 dict begin
- /BXlevel 0 def
- /BGDefault currentblackgeneration def
- /UCRDefault currentundercolorremoval def
- %****** DOESN'T HANDLE COLOR TRANSFER YET ******
- /TRDefault currenttransfer def
- matrix currentmatrix 2 dict
- 2 index /CropBox knownoget {
- oforce_elems boxrect 4 array astore 1 index /ClipRect 3 -1 roll put
- } if
- dictbeginpage setmatrix
- /DefaultQstate qstate store
-
- dup % for showing annotations below
- count 1 sub /pdfemptycount exch store
- % If the page uses any transparency features, show it within
- % a transparency group.
- dup pageusestransparency dup /PDFusingtransparency exch def {
- % Show the page within a PDF 1.4 device filter.
- 0 .pushpdf14devicefilter {
- % If the page has a Group, enclose contents in transparency group.
- % (Adobe Tech Note 5407, sec 9.2)
- dup /Group knownoget {
- 1 index /CropBox knownoget not {
- 1 index /MediaBox pget pop
- } if oforce_array .beginformgroup {
- showpagecontents
- } .internalstopped {
- .discardtransparencygroup stop
- } if .endtransparencygroup
- } {
- showpagecontents
- } ifelse
- } .internalstopped {
- % todo: discard
- .popdevicefilter stop
- } if .popdevicefilter
- } {
- showpagecontents
- } ifelse
- % check for extra garbage on the ostack and clean it up
- count pdfemptycount sub dup 0 ne {
- ( **** File did not complete the page properly and may be damaged.\n)
- pdfformaterror
- { pop } repeat
- } {
- pop
- } ifelse
- % todo: mixing drawing ops outside the device filter could cause
- % problems, for example with the pnga device.
- /Annots knownoget { { oforce drawannot } forall } if
- endpage
- end % scratch dict
- % Some PDF files don't have matching q/Q (gsave/grestore) so we need
- % to clean up any left over dicts from the dictstack
- countdictstack PDFdictstackcount sub dup 0 ne {
- ( **** Warning: File has imbalanced q/Q operators \(too many q's\)\n)
- pdfformaterror
- { end } repeat
- } {
- pop
- } ifelse
- (after exec) VMDEBUG
- Repaired % pass Repaired state around the restore
- PDFSave restore
- /Repaired exch def
- } bind def
- /showpagecontents { % <pagedict> showpagecontents -
- gsave % preserve gstate for Annotations later
- /Contents knownoget not { 0 array } if
- dup type /arraytype ne { 1 array astore } if {
- oforce false resolvestream pdfopdict .pdfrun
- } forall
- grestore
- } bind def
- /processcolorspace { % - processcolorspace <colorspace>
- % The following is per the PLRM3.
- currentdevice 1 dict dup /ProcessColorModel dup put .getdeviceparams
- exch pop exch pop
- dup type /nametype ne { cvn } if
- dup { setcolorspace } .internalstopped { pop /DeviceRGB } if
- } bind def
-
- % ------ Transparency support ------ %
-
- % Define minimum PDF version for checking for transparency features.
- % Transparency is a 1.4 feature however we have seen files that claimed
- % to be PDF 1.3 with transparency features.
- /PDFtransparencyversion 1.3 def
-
- % Determine whether a page might invoke any transparency features:
- % - Non-default BM, ca, CA, or SMask in an ExtGState
- % - Image XObject with SMask
- % Note: we deliberately don't check to see whether a Group is defined,
- % because Adobe Illustrator 10 (and possibly other applications) define
- % a page-level group whether transparency is actually used or not.
- % Ignoring the presence of Group is justified because, in the absence
- % of any other transparency features, they have no effect.
- /pageusestransparency { % <pagedict> pageusestransparency <bool>
- PDFversion PDFtransparencyversion lt NOTRANSPARENCY or {
- pop false
- } {
- false exch {
- dup resourceusestransparency { pop not exit } if
- /Parent knownoget not { exit } if
- } loop
- } ifelse
- } bind def
- % Check the Resources of a page or Form.
- /resourceusestransparency { % <dict> resourceusestransparency <bool>
- { % Use loop to provide an exitable context.
- /Resources knownoget not { 0 dict } if
- dup /ExtGState knownoget {
- false exch {
- exch pop oforce
- dup /BM knownoget { dup /Normal ne exch /Compatible ne and
- { pop not exit } if
- } if
- dup /ca knownoget { 1 ne { pop not exit } if } if
- dup /CA knownoget { 1 ne { pop not exit } if } if
- dup /SMask knownoget { /None ne { pop not exit } if } if
- pop
- } forall { pop true exit } if
- } if
- dup /XObject knownoget {
- false exch {
- exch pop oforce dup /Subtype get
- dup /Image eq { 1 index /SMask known { pop pop not exit } if } if
- /Form eq {
- resourceusestransparency { not exit } if
- } {
- pop
- } ifelse
- } forall { pop true exit } if
- } if
- pop false exit
- } loop
- } bind def
-
- % ------ ColorSpace substitution support ------ %
-
- %
- % <pagedict> pdfshowpage_setcspacesub <pagedict>
- %
- % Set up color space substitution for a page. Invocations of this procedure
- % must be bracketed by the save/restore operation for the page, to avoid
- % unintended effects on other pages.
- %
- % If any color space substitution is used, and the current color space is a
- % device dependent color space, make sure the current color space is updated.
- % There is an optimization in the setcolorspace pseudo-operator that does
- % nothing if both the current and operand color spaces are the same. For
- % PostScript this optimization is disabled if the UseCIEColor page device
- % parameter is true. This is not the case for PDF, as performance suffers
- % significantly on some PDF files if color spaces are set repeatedly. Hence,
- % if color space substitution is to be used, and the current color space
- % is a device dependent color space, we must make sure to "transition" the
- % current color space.
- %
- /pdfshowpage_setcspacesub
- {
- false
- { /DefaultGray /DefaultRGB /DefaultCMYK }
- {
- dup 3 index /ColorSpace //rget exec
- { resolvecolorspace /ColorSpace defineresource pop }
- { pop }
- ifelse
- }
- forall
-
- % if using color space substitution, "transition" the current color space
- {
- currentcolorspace dup length 1 eq % always an array
- {
- 0 get
- dup /DeviceGray eq 1 index /DeviceRGB eq or 1 index /DeviceCMYK or
- { /Pattern setcolorspace setcolorspace }
- { pop }
- ifelse
- }
- { pop }
- if
- }
- if
- }
- bind def
-
-
-
- end % pdfdict
- .setglobal
-